home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / progs / sviluppo / pike-0.4.0 / src / modules / arexx / arexx.c next >
C/C++ Source or Header  |  1997-01-10  |  8KB  |  367 lines

  1. /*
  2.    ARexx IPC for Amiga Pike
  3.  
  4.    Copyright (c) 1996 by Bernhard Fastenrath
  5.    (fasten@cs.bonn.edu / fasten@shw.com)
  6.  
  7.    This file may be distributed under the terms
  8.    of the GNU General Public License.
  9. */
  10.  
  11. #include "global.h"
  12. #include "error.h"
  13. #include "types.h"
  14. #include "svalue.h"
  15. #include "stralloc.h"
  16. #include "pike_types.h"
  17. #include "constants.h"
  18. #include "interpret.h"
  19. #include "arexx.h"
  20.  
  21. /* arexx_addlib() currently works only if compiled with SAS/C
  22.    because it requires the following #pragma
  23. */
  24. #ifdef __SASC
  25. #pragma libcall RexxFunctionHostLibrary RexxCall 1e 901
  26. struct Library *RexxFunctionHostLibrary = NULL;
  27. #endif
  28.  
  29. #if defined (__SASC)
  30. #define RXSLIB struct Library
  31. #elif defined (__GNUC__)
  32. #define RXSLIB struct RxsLib
  33. #endif
  34.  
  35. struct Library *ScriptBase = NULL;
  36. RXSLIB *RexxSysBase = NULL;
  37.  
  38. static struct RexxMsg *Rmsg = NULL;
  39. static struct MsgPort *MyPort = NULL;
  40. static char RexxHost[60] = "rexx_ced";
  41. static int RexxArgc = 0;
  42. static List LibraryList;
  43. static struct ScriptContext *ScriptC = NULL;
  44.  
  45. /*** pike functions ***/
  46.  
  47. void
  48. f_arexx_addlib (INT32 args)
  49. {
  50.   char *str;
  51.   Node *n;
  52.  
  53.   if (args < 1)
  54.     error ("Too few arguments to arexx_addlib().\n");
  55.  
  56.   if (sp[-args].type != T_STRING)
  57.     error ("Bad argument 1 to arexx_addlib().\n");
  58.  
  59.   str = sp[-args].u.string->str;
  60.   if (!FindName (&LibraryList, str))
  61.   {
  62.     if (!(n = (Node *) malloc (sizeof (Node))))
  63.       error ("Out of memory.\n");
  64.     if (!(n -> ln_Name = malloc (strlen (str + 1))))
  65.     {
  66.       free (n);
  67.       error ("Out of memory.\n");
  68.     }
  69.     strcpy (n -> ln_Name, str);
  70.     AddHead (&LibraryList, n);
  71.   }
  72.   pop_n_elems (args);
  73.   push_int (1);
  74. }
  75.  
  76. void
  77. f_arexx_host (INT32 args)
  78. {
  79.   if (args < 1)
  80.     error ("Too few arguments to arexx_host().\n");
  81.  
  82.   if (sp[-args].type != T_STRING)
  83.     error ("Bad argument 1 to arexx_host().\n");
  84.  
  85.   strncpy (RexxHost, sp[-args].u.string->str, 60);
  86.  
  87.   pop_n_elems (args);
  88. }
  89.  
  90. void
  91. f_arexx_import (INT32 args)
  92. {
  93.   char *variable_value;
  94.   struct pike_string *ret;
  95.  
  96.   if (args < 1)
  97.     error ("Too few arguments to arexx_import().\n");
  98.  
  99.   if(sp[-args].type != T_STRING)
  100.     error("Bad argument 1 to arexx_import().\n");
  101.  
  102.   Script_GetStringVar (ScriptC, sp[-args].u.string->str, &variable_value);
  103.  
  104.   if (variable_value)
  105.     ret = make_shared_string (variable_value);
  106.   else
  107.     ret = make_shared_string ("");
  108.  
  109.   pop_n_elems (args);
  110.   push_string (ret);
  111. }
  112.  
  113. void
  114. f_arexx_export (INT32 args)
  115. {
  116.   char *variable_name, *variable_value;
  117.  
  118.   if (args < 2)
  119.     error ("Too few arguments to arexx_export().\n");
  120.  
  121.   if(sp[-args].type != T_STRING)
  122.     error ("Bad argument 1 to arexx_export().\n");
  123.  
  124.   if(sp[-args+1].type != T_STRING)
  125.     error ("Bad argument 2 to arexx_export().\n");
  126.  
  127.   variable_name  = sp[-args].u.string->str;
  128.   variable_value = sp[-args+1].u.string->str;
  129.  
  130.   switch (Script_SetStringVar (ScriptC, variable_name, variable_value))
  131.   {
  132.     case 0:
  133.       break;
  134.     case ERR10_003:
  135.       error ("Insufficient Storage");
  136.     case ERR10_009:
  137.       error ("String too long");
  138.     default:
  139.       error ("Unknown error");
  140.   }
  141.   pop_n_elems (args);
  142. }
  143.  
  144. void
  145. f_arexx_cmd (INT32 args)
  146. {
  147.   int t, return_code;
  148.  
  149.   if (args < 1)
  150.     error ("Too few arguments to arexx_cmd().\n");
  151.  
  152. #ifdef __SASC
  153.   if (FindName (&LibraryList, RexxHost))
  154.   {
  155.     for (t=0; t<args; t++)
  156.     {
  157.       if (sp[-args+t].type != T_STRING)
  158.         error ("Bad argument type: arexx arguments must be strings.\n");
  159.       if (!SetARexxArg (t, (char *) sp[-args+t].u.string->str))
  160.         error ("out of memory.\n");
  161.     }
  162.     if (!ArexxLibraryCommand (&return_code))
  163.       error ("Invalid rexx library parameter.\n");
  164.   }
  165.   else
  166. #endif
  167.   {
  168.     char s[256], *str, *ptr = s;
  169.     int len, rem = 255;
  170.  
  171.     for (t=0; t<args; t++)
  172.     {
  173.       if (sp[-args+t].type != T_STRING)
  174.         error ("Bad argument type: arexx arguments must be strings.\n");
  175.       len = strlen (str = (char *) sp[-args+t].u.string->str);
  176.       if (len > rem)
  177.         error ("Arexx command exceeds 256 characters.\n");
  178.       strcpy (ptr, str);
  179.       rem -= len;
  180.       ptr += len;
  181.       *ptr = ' ';
  182.       ptr ++;
  183.     }
  184.     *(ptr-1) = '\0';
  185.  
  186.     if (!ArexxCommand (s, &return_code))
  187.       error ("Bad rexx host parameter.\n");
  188.   }
  189.   pop_n_elems (args);
  190.   push_int (return_code);
  191. }
  192.  
  193. /*** module interface ***/
  194.  
  195. void exit_arexx (void);
  196.  
  197. void
  198. init_arexx_efuns (void)
  199. {
  200.   atexit (exit_arexx);
  201.  
  202.   NewList (&LibraryList);
  203.  
  204.   if (!(RexxSysBase = (struct RxsLib *) OpenLibrary ("rexxsyslib.library", 36)))
  205.     return;
  206.  
  207.   if (!(MyPort = CreateMsgPort ()))
  208.     return;
  209.  
  210.   if (!(Rmsg = CreateRexxMsg (MyPort, NULL, NULL)))
  211.     return;
  212.  
  213.   if (!(ScriptBase = OpenLibrary ("script.library", 0)))
  214.     return;
  215.  
  216.   if (!(ScriptC = Script_AllocContext ()))
  217.     return;
  218.  
  219.   Script_SetMsgContext (Rmsg, ScriptC);
  220.  
  221.   add_efun ("arexx_addlib", f_arexx_addlib,  "function(mixed ... : int)", OPT_SIDE_EFFECT);
  222.   add_efun ("arexx_host", f_arexx_host, "function(string : void)", OPT_SIDE_EFFECT);
  223.   add_efun ("arexx_export", f_arexx_export,  "function(string, string : void)", OPT_SIDE_EFFECT);
  224.   add_efun ("arexx_import", f_arexx_import,  "function(string : string)", OPT_SIDE_EFFECT);
  225.   add_efun ("arexx_cmd", f_arexx_cmd,  "function(mixed ... : int)", OPT_SIDE_EFFECT);
  226. }
  227.  
  228. void
  229. init_arexx_programs (void)
  230. {}
  231.  
  232. void
  233. exit_arexx (void)
  234. {
  235.   Node *n;
  236.  
  237.   if (!RexxSysBase)
  238.     return;
  239.  
  240.   while (n = RemHead (&LibraryList))
  241.   {
  242.     free (n -> ln_Name);
  243.     free (n);
  244.   }
  245.   if (ScriptC)
  246.     Script_FreeContext (ScriptC);
  247.   if (Rmsg)
  248.     DeleteRexxMsg (Rmsg);
  249.   if (MyPort)
  250.     DeleteMsgPort (MyPort);
  251.   if (RexxSysBase)
  252.     CloseLibrary ((struct Library *) RexxSysBase);
  253.   if (ScriptBase)
  254.     CloseLibrary (ScriptBase);
  255.  
  256.   RexxSysBase = NULL;
  257. }
  258.  
  259. /*** internal functions ***/
  260.  
  261. static void
  262. ClearRexxResult (struct RexxMsg *r)
  263. {
  264.   /**  Hmmm :-) Probably correct.
  265.    **  (My docs don't mention it)
  266.    **/
  267.  
  268.   if (r -> rm_Result2)
  269.   {
  270.     DeleteArgstring ((UBYTE *) r -> rm_Result2);
  271.     r -> rm_Result2 = 0;
  272.   }
  273. }
  274.  
  275. static int
  276. SetARexxArg (int n, char *arg)
  277. {
  278.   RexxArgc = n;
  279.   return (int) (Rmsg -> rm_Args[n] = CreateArgstring (arg, strlen (arg)));
  280. }
  281.  
  282. static int
  283. ArexxCommand (char *cmd, int *rc)
  284. {
  285.   struct MsgPort *hport;
  286.  
  287.   if (!(Rmsg -> rm_Args[0] = CreateArgstring (cmd, strlen (cmd))))
  288.     error ("Out of memory.\n");
  289.   Rmsg -> rm_Node.mn_Node.ln_Type = NT_MESSAGE;
  290.   Rmsg -> rm_Node.mn_Length = sizeof (struct RexxMsg);
  291.   Rmsg -> rm_Action = RXFUNC | RXFF_RESULT;
  292.   Rmsg -> rm_Node.mn_ReplyPort = MyPort;
  293.  
  294.   Forbid ();
  295.   if (!(hport = FindPort (RexxHost)))
  296.   {
  297.     Permit ();
  298.     return 0;
  299.   }
  300.   PutMsg (hport, (struct Message *) Rmsg);
  301.   Permit ();
  302.   do
  303.     WaitPort (MyPort);
  304.   while (GetMsg (MyPort) != (struct Message *) Rmsg);
  305.  
  306.   if (Rmsg -> rm_Result2)
  307.     *rc = atoi ((char *) Rmsg -> rm_Result2);
  308.   else
  309.     *rc = Rmsg -> rm_Result1;
  310.  
  311.   ClearRexxMsg (Rmsg, 1);
  312.   ClearRexxResult (Rmsg);
  313.   return 1;
  314. }
  315.  
  316. #ifdef __SASC
  317. static int
  318. ArexxLibraryCommand (int *rc)
  319. {
  320.   if (!(RexxFunctionHostLibrary = OpenLibrary (RexxHost, 0L)))
  321.     return 0;
  322.  
  323. #ifdef DEBUG
  324.   PrintRexxArgs (Rmsg);
  325. #endif
  326.  
  327.   Rmsg -> rm_Action = RXFUNC | RXFF_RESULT | RexxArgc;
  328.   RexxCall (Rmsg);
  329.   CloseLibrary (RexxFunctionHostLibrary);
  330.  
  331. #ifdef DEBUG
  332.   PrintRexxArgs (Rmsg);
  333. #endif
  334.  
  335.   if (Rmsg -> rm_Result2)
  336.     *rc = atoi ((char *) Rmsg -> rm_Result2);
  337.   else
  338.     *rc = Rmsg -> rm_Result1;
  339.  
  340.   ClearRexxMsg (Rmsg, RexxArgc + 1);
  341.   ClearRexxResult (Rmsg);
  342.  
  343.   RexxArgc = 0;
  344.   return 1;
  345. }
  346. #endif
  347.  
  348. #ifdef DEBUG
  349. static int
  350. PrintRexxArgs (struct RexxMsg *rm)
  351. {
  352.   int t;
  353.  
  354.   printf ("--- printargs ---\n");
  355.   for (t=0; t <= MAXRMARG; t++)
  356.   {
  357.     if (rm -> rm_Args[t])
  358.       printf ("Arg[%d] = \"%s\".\n", t, rm -> rm_Args[t]);
  359.   }
  360.   if (rm -> rm_Result2)
  361.     printf ("Result = \"%s\".\n", rm -> rm_Result2);
  362.   else
  363.     printf ("Result = <null>.\n");
  364.   return 0;
  365. }
  366. #endif
  367.